home *** CD-ROM | disk | FTP | other *** search
/ Delphi 2 - Developers' Solutions / Delphi 2 Developers' Solutions.iso / dds / chap02 / howto03 / drwsutl2.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-03-05  |  53.0 KB  |  1,446 lines

  1. unit Drwsutl2;
  2.  
  3. interface
  4.  
  5. uses
  6.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  7.   Forms, Dialogs, StdCtrls, Buttons, ExtCtrls, ShellAPI, FileCtrl, DRWSUtl1;
  8.  
  9. const
  10.   EOC_CHANGEDIR = 1;  { Error Operation Code for change directory failure }
  11.   EOC_SOURCECOPY = 2; { Error Operation Code for source copy failure      }
  12.   EOC_DESTCOPY = 3;   { Error Operation Code for destination copy failure }
  13.   EOC_DELETEFILE = 4; { Error Operation Code for file delete failure      }
  14.   EOC_DELETEDIR = 5;  { Error Operation Code for directory delete failure }
  15.   EOC_RENAMEFILE = 6; { Error Operation Code for renaming failure         }
  16.   EOC_MAKEDIR = 7;    { Error Operation Code for MkDir failure            }
  17.   EOC_SETATTR = 8;    { Error Operation Code for Set Attributes failure   }
  18.  
  19.   FAC_COPY = 1;       { File Action Code for recursive copying            }
  20.   FAC_MOVE = 2;       { File Action Code for recursive moving             }
  21.   FAC_DELETE = 3;     { File Action Code for recursive deletion           }
  22. type
  23.   { This is a descendant of TFileListbox }
  24.   { Which puts icons of files into the   }
  25.   { Objects array rather than the stand- }
  26.   { ard bitmaps.                         }
  27.   TIconFileListBox = class( TFileListBox )
  28.   public
  29.     { public methods and data }
  30.     function GetNextSelection( SourceDirectory : String;
  31.               var CurrentItem : Integer ) : String;
  32.   end;
  33.   TFileWorkBench = class( TComponent )
  34.   public
  35.     GlobalError        : Integer;  { This is used by FMXUCopyFile for er code }
  36.     GlobalErrorType    : Integer;  { This holds the Operation code            }
  37.     function ForceTrailingBackSlash( const TheFileName : String ) : String;
  38.     function StripNonRootTrailingBackSlash(
  39.               const TheFileName : String ) : String;
  40.     procedure GetFileAttributes( TheFile : String; var IsDirectory , IsArchive ,
  41.                 IsVolumeID , IsHidden , IsReadOnly , IsSysFile : Boolean );
  42.     procedure HandleIOException( TheOpCode : Integer; ThePath : String;
  43.                                  TheMessage : String; TheCode : Integer );
  44.     procedure HandleDOSError( TheOpCode : Integer; ThePath : String;
  45.                 TheCode : Integer );
  46.     procedure FMXUCopyFile(const FileName, DestName: String);
  47.     function CopyFile( TargetPath ,
  48.                DestinationPath : String ) : Boolean;
  49.     procedure ChangeTheDirectory( NewPath : String );
  50.     procedure ChangeTheDriveAndDirectory( NewDrive : Integer );
  51.     procedure CopyTheFile( OldPath , NewPath : String );
  52.     procedure MoveTheFile( OldPath , NewPath : String );
  53.     procedure DeleteTheFile( ThePath : String );
  54.     procedure RenameTheFile( OldPath , NewName : String );
  55.     procedure CreateNewDirectory( NewPath : String );
  56.     procedure RemoveDirectory( ThePath : String );
  57.   end;
  58.   TFileIconPanel = class( TPanel )
  59.   private
  60.     { Private declarations }
  61.     FHighlightColor : TColor;                 { This holds bright edge bevel }
  62.     FShadowColor    : TColor;                 { This holds dark edge bevel   }
  63.     procedure TheClick( Sender : TObject );   { This holds override click    }
  64.   protected                                   { event method procedure.      }
  65.     { Protected declarations }
  66.     procedure Paint; override;                { This allows custom painting  }
  67.   public
  68.     { Public declarations }
  69.     FTheIcon : TIcon;                         { This is the display icon    }
  70.     FTheName : String;                        { This is the filename        }
  71.     FTheLabel : TLabel;                       { This is the display label   }
  72.     Selected : Boolean;                       { This holds selection status }
  73.     constructor Create(AOwner : TComponent); override; { override create    }
  74.     procedure Initialize( PanelX              ,             { Left          }
  75.                           PanelY              ,             { Top           }
  76.                           PanelWidth          ,             { Width         }
  77.                           PanelHeight         ,             { Height        }
  78.                           PanelBevelWidth     ,             { Bevel Width   }
  79.                           LabelFontSize         : Integer;  { Font size     }
  80.                           PanelColor          ,             { Main color    }
  81.                           PanelHighlightColor ,             { Bright color  }
  82.                           PanelShadowColor    ,             { Dark color    }
  83.                           LabelTextColor        : TColor;   { Text color    }
  84.                           TheFilename         ,             { Filename      }
  85.                           LabelFontName         : String;   { Font name     }
  86.                           LabelFontStyle        : TFontStyles;  { Font style}
  87.                           ExtraData             : Integer       );  { Drive }
  88.     destructor Destroy; override;             { override destroy to free    }
  89.   end;
  90.   TFileIconPanelScrollBox = class( TScrollBox )
  91.   public
  92.     { Public methods and data }
  93.     TheFWB              : TFileWorkBench; { Used for file manipulation         }
  94.     IconsNeedRefreshing : Boolean;                   { Flag to redo display    }
  95.     TheIconSize        : Integer;   { Holds Individual Icon size               }
  96.     TheIconSpacing     : Integer;   { Holds total icon footprint               }
  97.     MaxIconsInARow     : Integer;   { Set for screen size.                     }
  98.     TheStoredHandle    : HWnd;
  99.     procedure Update;                                { Called to reset display }
  100.     constructor Create( AOwner : TComponent ); override;  { Override inherited }
  101.     procedure ClearTheFIPs;                          { Clears the FIPs safely  }
  102.     procedure AddDriveIcons( var XCounter , YCounter : Integer ); { Add drives }
  103.     procedure GetColorsForFileIcon( TheFile : String;
  104.                var BC , HC , SC , TC : TColor );
  105.     procedure GetIconsForEntireDirectory( TargetPath  : String );
  106.     function GetNextSelection( SourceDirectory : String;
  107.               var CurrentItem : Integer ) : String;
  108.   end;
  109.  
  110.   { This procedure gets an icon for a file using FindExecutable  }
  111.   { and ExtractIcon. (assumes file/dir is passed)                }
  112.   procedure GetIconForFile( TheName : String; var TheIcon : TIcon );
  113.   { This procedure spaces out the bitbtn components on a tpanel }
  114.   procedure SpacePanelButtons( WhichPanel : TPanel );
  115.  
  116. implementation
  117. {$R DRWSUTL2.RES}                 { Import custom resource file }
  118.  
  119. { This procedure spaces out the bitbtn components on a tpanel }
  120. procedure SpacePanelButtons( WhichPanel : TPanel );
  121. var TheCalculatedSpacing     ,            { Holds primary spacing }
  122.     TheFullCalculatedSpacing   : Integer; { Holds full spacing    }
  123.     Counter_1                  : Integer; { Loop counter          }
  124.     TotalIBs                   : Integer; { Gets total buttons    }
  125. begin
  126.   { Set up spacing values }
  127.   TotalIBs := WhichPanel.ControlCount;
  128.   TheCalculatedSpacing := (( WhichPanel.Width - 6 - ( TotalIbs * 49 ))
  129.    div ( TotalIbs + 1 ));
  130.   TheFullCalculatedSpacing := TheCalculatedSpacing + 49;
  131.   { Loop through all imported buttons and set their Left values }
  132.   for Counter_1 := 1 to WhichPanel.ControlCount do
  133.   begin
  134.     if Counter_1 = 1 then
  135.     begin
  136.       TBitBtn( WhichPanel.Controls[ Counter_1 - 1 ] ).Left := 3 +
  137.        TheCalculatedSpacing;
  138.     end
  139.     else
  140.     begin
  141.       TBitBtn( WhichPanel.Controls[ Counter_1 - 1 ] ).Left := 3 +
  142.        (( Counter_1 - 1 ) * TheFullCalculatedSpacing ) + TheCalculatedSpacing;
  143.     end;
  144.   end;
  145. end;
  146.  
  147. { This procedure gets an icon for a file using FindExecutable  }
  148. { and ExtractIcon. (assumes file/dir is passed)                }
  149. procedure GetIconForFile( TheName : String; var TheIcon : TIcon );
  150. var TheExt           : String; { File extension holder }
  151.     TheOtherPChar  ,           { Windows ASCIIZ string }
  152.     ThePChar         : PChar;  { Windows ASCIIZ string }
  153.     Dummy : Word;
  154. begin
  155.   { Check for directory and if so get directory icon from RES file }
  156.   if (( FileGetAttr( TheName ) and faDirectory ) = faDirectory ) then
  157.   begin
  158.     { Set up the PChar to communicate with Windows }
  159.     GetMem( TheOtherPChar , 255 );
  160.     { Convert Pascal-style string to ASCIIZ Pchar }
  161.     StrPCopy( TheOtherPChar , 'DIRECTORY' );
  162.     { Use API call to return icon handle of Icon Resource in FILECTRL.RES }
  163.     TheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  164.     { Release memory from PChar }
  165.     FreeMem( TheOtherPChar , 255 );
  166.     { Leave }
  167.     exit;
  168.   end;
  169.   { Assume archive file; get its extension }
  170.   TheExt := Uppercase( ExtractFileExt( TheName ));
  171.   { If not an executable/image file then use FindExecutable to get icon }
  172.   if (( TheExt <> '.EXE' ) and ( TheExt <> '.BAT' ) and
  173.       ( TheExt <> '.PIF' ) and ( TheExt <> '.COM' )) then
  174.   begin
  175.     { Grab three chunks of memory }
  176.     GetMem( ThePChar , 255 );
  177.     { Set up the name and its directory in Windows string formats }
  178.     StrPCopy( ThePChar, TheName );
  179.     Dummy := 65535;
  180.     {**** Windows 95 Specialized call ****** }
  181.     TheIcon.Handle := ExtractAssociatedIcon( hInstance , ThePChar , Dummy );
  182.     if TheIcon.Handle = 0 then
  183.     begin
  184.       GetMem( TheOtherPChar , 255 );
  185.       StrPCopy( TheOtherPChar , 'NOICON' );
  186.       TheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  187.       FreeMem( TheOtherPChar , 255 );
  188.       exit;
  189.     end;
  190.     FreeMem( ThePChar , 255 );
  191.   end
  192.   else
  193.   { Assume Windows Executable file, so get icon from it with ExtractIcon API }
  194.   begin
  195.     GetMem( ThePChar , 255 );
  196.     StrPCopy( ThePChar , TheName );
  197.     { Try to get first icon for file }
  198.     Dummy := 65535;
  199.     TheIcon.Handle := ExtractAssociatedIcon( hInstance , ThePChar , Dummy );
  200.     FreeMem( ThePChar , 255 );
  201.     { If handle is 0 invalid icon format so use default from RES file }
  202.     if TheIcon.Handle = 0 then
  203.     begin
  204.       GetMem( TheOtherPChar , 255 );
  205.       StrPCopy( TheOtherPChar , 'NOICON' );
  206.       TheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  207.       FreeMem( TheOtherPChar , 255 );
  208.       exit;
  209.     end;
  210.   end;
  211. end;
  212.  
  213. { This procedure does a fully error-trapped change directory }
  214. procedure TFileWorkBench.ChangeTheDirectory( NewPath : String );
  215. var CurrentDirectory : String;
  216. begin
  217.   if NewPath = '..' then
  218.   begin { Back up one level }
  219.     {$I+}
  220.     try
  221.       { Find the current directory }
  222.       GetDir( 0 , CurrentDirectory );
  223.       { Use EFP to move up one level }
  224.       CurrentDirectory := ExtractFilePath( CurrentDirectory );
  225.       { Strip trailing \ if not root }
  226.       CurrentDirectory := StripNonRootTrailingBackSlash( CurrentDirectory );
  227.       { Try the change to the new drive }
  228.       ChDir( CurrentDirectory );
  229.     except
  230.       { if any exception occurs instantiate exception and show }
  231.       On E:EInOutError do
  232.       begin
  233.         { Call custom error display/lookup procedure }
  234.         HandleIOException( EOC_CHANGEDIR , CurrentDirectory ,
  235.          E.Message , E.ErrorCode );
  236.       end;
  237.     end;
  238.   end
  239.   else
  240.   begin { Change to explicit path }
  241.     {$I+}
  242.     try
  243.       { Get target directory path }
  244.       CurrentDirectory := NewPath;
  245.       { Strip trailing \ if not root }
  246.       CurrentDirectory := StripNonRootTrailingBackSlash( CurrentDirectory );
  247.       { Try the change to the new drive }
  248.       ChDir( CurrentDirectory );
  249.     except
  250.       { if any exception occurs instantiate exception and show }
  251.       On E:EInOutError do
  252.       begin
  253.         { Call custom error display/lookup procedure }
  254.         HandleIOException( EOC_CHANGEDIR , CurrentDirectory ,
  255.          E.Message , E.ErrorCode );
  256.       end;
  257.     end;
  258.   end;
  259. end;
  260.  
  261. { This procedure does a fully error-trapped change directory }
  262. procedure TFileWorkBench.ChangeTheDriveAndDirectory( NewDrive : Integer );
  263. var CurrentDirectory : String;
  264. begin
  265.   {$I+}
  266.   try
  267.     { Find the working directory on new drive }
  268.     GetDir( NewDrive , CurrentDirectory );
  269.     { Try the change to the new drive }
  270.     ChDir( CurrentDirectory );
  271.   except
  272.     { if any exception occurs instantiate exception and show }
  273.     On E:EInOutError do
  274.     begin
  275.       { Call custom error display/lookup procedure }
  276.       HandleIOException( EOC_CHANGEDIR , CurrentDirectory ,
  277.        E.Message , E.ErrorCode );
  278.     end;
  279.   end;
  280. end;
  281.  
  282. { This procedure copies a single file with error trapping }
  283. procedure TFileWorkBench.CopyTheFile( OldPath , NewPath : String );
  284. var AResult : Boolean; { Internal data flag }
  285. begin
  286.   { If Copyfile returns false an error occurred }
  287.   AResult := CopyFile( OldPath , NewPath +
  288.    ExtractFileName( OldPath ));
  289.   { Display meaningful error message }
  290.   if not AResult then HandleDOSError( GlobalErrorType ,
  291.    ExtractFileName( OldPath ) , GlobalError );
  292. end;
  293.  
  294. { This procedure moves a file by copying and delete it }
  295. procedure TFileWorkBench.MoveTheFile( OldPath , NewPath : String );
  296. var AResult : Boolean; { Internal data flag }
  297.     TheFile : File;    { Use to get errors  }
  298. begin
  299.   { If Copyfile returns false an error occurred }
  300.   AResult := CopyFile( OldPath , NewPath +
  301.     ExtractFileName( OldPath ));
  302.   { Display meaningful error message }
  303.   if not AResult then HandleDOSError( GlobalErrorType ,
  304.    ExtractFileName( OldPath ), GlobalError );
  305.   { After valid copying, delete source file }
  306.   {$I+}
  307.   if AResult then try
  308.     { Use this trick to get valid exception handling }
  309.     AssignFile( TheFile , OldPath );
  310.     { Use erase because Deletefile doesn't give exceptions! }
  311.     Erase( TheFile );
  312.   except
  313.     { if any exception occurs instantiate exception and show }
  314.     On E:EInOutError do
  315.     begin
  316.       { Call custom error display/lookup procedure }
  317.       HandleIOException( EOC_DELETEFILE , ExtractFileName( OldPath ) ,
  318.        E.Message , E.ErrorCode );
  319.     end;
  320.   end;
  321. end;
  322.  
  323. { This procedure safely deletes a single file }
  324. procedure TFileWorkBench.DeleteTheFile( ThePath : String );
  325. var TheFile : File; { Internal file handle }
  326. begin
  327.   {$I+}
  328.   try
  329.     { Use this trick to get valid exception handling }
  330.     AssignFile( TheFile , ThePath );
  331.     { Use erase because Deletefile doesn't give exceptions! }
  332.     Erase( TheFile );
  333.   except
  334.     { if any exception occurs instantiate exception and show }
  335.     On E:EInOutError do
  336.     begin
  337.       { Call custom error display/lookup procedure }
  338.       HandleIOException( EOC_DELETEFILE , ExtractFileName( ThePath ) ,
  339.        E.Message , E.ErrorCode );
  340.     end;
  341.   end;
  342. end;
  343.  
  344. { This procedure renames a file with full error trapping }
  345. procedure TFileWorkBench.RenameTheFile( OldPath , NewName : String );
  346. var TheFile : File; { Internal file handle }
  347. begin
  348.   {$I+}
  349.   try
  350.     { Use this trick to get valid exception handling }
  351.     AssignFile( TheFile , OldPath );
  352.     { Use this because RenameFile doesn't give exceptions! }
  353.     Rename( TheFile , NewName );
  354.   except
  355.     { if any exception occurs instantiate exception and show }
  356.     On E:EInOutError do
  357.     begin
  358.       { Call custom error display/lookup procedure }
  359.       HandleIOException( EOC_RENAMEFILE , ExtractFileName( OldPath ) ,
  360.        E.Message , E.ErrorCode );
  361.     end;
  362.   end;
  363. end;
  364.  
  365. { This procedure creates a new directory with full error trapping }
  366. procedure TFileWorkBench.CreateNewDirectory( NewPath : String );
  367. begin
  368.   {$I+}
  369.   try
  370.     Mkdir( NewPath );
  371.   except
  372.     { if any exception occurs instantiate exception and show }
  373.     On E:EInOutError do
  374.     begin
  375.       { Call custom error display/lookup procedure }
  376.       HandleIOException( EOC_MAKEDIR , ExtractFileName( NewPath ) ,
  377.        E.Message , E.ErrorCode );
  378.     end;
  379.   end;
  380. end;
  381.  
  382. { This procedure remove a directory with full error trapping }
  383. procedure TFileWorkBench.RemoveDirectory( ThePath : String );
  384. begin
  385.   {$I+}
  386.   try
  387.     Rmdir( ThePath );
  388.   except
  389.     { if any exception occurs instantiate exception and show }
  390.     On E:EInOutError do
  391.     begin
  392.       { Call custom error display/lookup procedure }
  393.       HandleIOException( EOC_DELETEDIR , ExtractFileName( ThePath ) ,
  394.        E.Message , E.ErrorCode );
  395.     end;
  396.   end;
  397. end;
  398.  
  399. { This is a generic copy routine taken from Delphi sample code }
  400. { It has been edited to return viable error codes!             }
  401. procedure TFileWorkBench.FMXUCopyFile(const FileName, DestName: String);
  402. var
  403.   CopyBuffer: Pointer; { buffer for copying }
  404.   BytesCopied: Longint;
  405.   TheAttr : Integer;
  406.   Source, Dest: Integer; { handles }
  407. const
  408.   ChunkSize: Longint = 8192; { copy in 8K chunks }
  409. begin
  410.   GetMem(CopyBuffer, ChunkSize); { allocate the buffer }
  411.   Source := FileOpen(FileName, fmShareDenyWrite); { open source file }
  412.   if Source < 0 then
  413.   begin  { error creating source file }
  414.     GlobalErrorType := EOC_SOURCECOPY;
  415.     GlobalError := -IOResult;
  416.     if GlobalError = 0 then GlobalError := -157;
  417.     FreeMem( CopyBuffer, ChunkSize );
  418.     exit;
  419.   end;
  420.   Dest := FileCreate(DestName); { create output file; overwrite existing }
  421.   if Dest < 0 then
  422.   begin  { error creating destination file }
  423.     FileClose( Source );
  424.     GlobalErrorType := EOC_DESTCOPY;
  425.     GlobalError := -IOResult;
  426.     if GlobalError = 0 then GlobalError := -159;
  427.     FreeMem( CopyBuffer , ChunkSize );
  428.     exit;
  429.   end;
  430.   {$I-}
  431.   repeat
  432.     BytesCopied := FileRead(Source, CopyBuffer^, ChunkSize); { read chunk}
  433.     if BytesCopied > 0 then { if we read anything... }
  434.     FileWrite(Dest, CopyBuffer^, BytesCopied); { ...write chunk }
  435.   until BytesCopied < ChunkSize; { until we run out of chunks }
  436.   {$I+}
  437.   GlobalError := -IOResult;  { get any error code which happens during copying }
  438.   FileClose(Dest); { close the destination file }
  439.   FileClose(Source); { close the source file }
  440.   FreeMem(CopyBuffer, ChunkSize); { free the buffer }
  441. end;
  442.  
  443. { This function calls the sample Copy code and handles errors }
  444. function TFileWorkBench.CopyFile( TargetPath ,
  445.           DestinationPath : String ) : Boolean;
  446. begin
  447.   { Set global error value to no error }
  448.   GlobalError := 0;
  449.   { Call the sample procedure to do the copy }
  450.   FMXUCopyFile( TargetPath, DestinationPath );
  451.   { If no error return true else return false }
  452.   if GlobalError < 0 then CopyFile := false else
  453.    CopyFile := true;
  454. end;
  455.  
  456. { This procedure handles displaying a user-friendly Dialog box with a }
  457. { Message for Delphi IO exception errors.                             }
  458. procedure TFileWorkBench.HandleIOException( TheOpCode : Integer;
  459.            ThePath : String; TheMessage : String; TheCode : Integer );
  460. var ErrorMessageString : String;  { Holds internal data }
  461.     OperationString    : String;  { Holds internal data }
  462. begin
  463.   { clear to check for unrecognized code }
  464.   ErrorMessageString := '';
  465.   { Check against imported code }
  466.   case TheCode of
  467.     2    : ErrorMessageString := 'File not found';
  468.     3    : ErrorMessageString := 'Path not found';
  469.     4    : ErrorMessageString := 'Too many open files';
  470.     5    : ErrorMessageString := 'File access denied';
  471.     6    : ErrorMessageString := 'Invalid file handle';
  472.     12    : ErrorMessageString := 'Invalid file access code';
  473.     15    : ErrorMessageString := 'Invalid drive number';
  474.     16  : ErrorMessageString := 'Cannot remove current directory';
  475.     17    : ErrorMessageString := 'Cannot rename across drives';
  476.     100    : ErrorMessageString := 'Disk read error';
  477.     101    : ErrorMessageString := 'Disk write error';
  478.     102    : ErrorMessageString := 'File not assigned';
  479.     103    : ErrorMessageString := 'File not open';
  480.     104    : ErrorMessageString := 'File not open for input';
  481.     105    : ErrorMessageString := 'File not open for output';
  482.   end;
  483.   case TheOpCode of
  484.     EOC_CHANGEDIR : OperationString := 'Unable to Change Directory due to ';
  485.     EOC_SOURCECOPY : OperationString := 'Unable to Copy due to Source File ';
  486.     EOC_DESTCOPY : OperationString := 'Unable to Copy due to Destination File ';
  487.     EOC_DELETEFILE : OperationString := 'Unable to Delete File due to ';
  488.     EOC_DELETEDIR : OperationString := 'Unable to Delete Directory due to ';
  489.     EOC_RENAMEFILE : OperationString := 'Unable to Rename File due to ';
  490.     EOC_MAKEDIR : OperationString := 'Unable to Create New Directory due to ';
  491.     EOC_SETATTR : OperationString := 'Unable to Set File Attributes due to ';
  492.   end;
  493.   { If not recognized use message; not a DOS error; reset cursor for neatness }
  494.   if ErrorMessageString = '' then
  495.   begin
  496.     Screen.Cursor := crDefault;
  497.     MessageDlg( OperationString + ExtractFileName( ThePath ) + ' ' +
  498.      TheMessage , mtError , [mbOK],0);
  499.   end
  500.   else
  501.   begin
  502.     { Recognized DOS exception, reset cursor for neatness }
  503.     Screen.Cursor := crDefault;
  504.     MessageDlg( OperationString + ExtractFileName( ThePath ) + ' ' +
  505.      ErrorMessageString , mtError , [mbOK], 0 );
  506.   end;
  507. end;
  508.  
  509. { This procedure handles displaying a user-friendly Dialog box with a }
  510. { Message for DOS error codes.                                        }
  511. procedure TFileWorkBench.HandleDOSError( TheOpCode : Integer;
  512.            ThePath : String;  TheCode : Integer );
  513. var ErrorMessageString : String;  { internal message holder }
  514.     OperationString : String;     { internal message holder }
  515. begin
  516.   { clear the message holder to check for unrecognized code }
  517.   ErrorMessageString := '';
  518.   { Negate the code back to normal number and check to set string }
  519.   case -TheCode of
  520.     2    : ErrorMessageString := 'File not found';
  521.     3    : ErrorMessageString := 'Path not found';
  522.     4    : ErrorMessageString := 'Too many open files';
  523.     5    : ErrorMessageString := 'File access denied';
  524.     6    : ErrorMessageString := 'Invalid file handle';
  525.     12    : ErrorMessageString := 'Invalid file access code';
  526.     15    : ErrorMessageString := 'Invalid drive number';
  527.     16  : ErrorMessageString := 'Cannot remove current directory';
  528.     17    : ErrorMessageString := 'Cannot rename across drives';
  529.     100    : ErrorMessageString := 'Disk read error';
  530.     101    : ErrorMessageString := 'Disk write error';
  531.     102    : ErrorMessageString := 'File not assigned';
  532.     103    : ErrorMessageString := 'File not open';
  533.     104    : ErrorMessageString := 'File not open for input';
  534.     105    : ErrorMessageString := 'File not open for output';
  535.     157 : ErrormessageString := 'Could not open Source File';
  536.     159 : ErrormessageString := 'Could not open Target File';
  537.   end;
  538.   case TheOpCode of
  539.     EOC_CHANGEDIR : OperationString := 'Unable to Change Directory due to ';
  540.     EOC_SOURCECOPY : OperationString := 'Unable to Copy due to Source File ';
  541.     EOC_DESTCOPY : OperationString := 'Unable to Copy due to Destination File ';
  542.     EOC_DELETEFILE : OperationString := 'Unable to Delete File due to ';
  543.     EOC_DELETEDIR : OperationString := 'Unable to Delete Directory due to ';
  544.     EOC_RENAMEFILE : OperationString := 'Unable to Rename File due to ';
  545.     EOC_MAKEDIR : OperationString := 'Unable to Create New Directory due to ';
  546.     EOC_SETATTR : OperationString := 'Unable to Set File Attributes due to ';
  547.   end;
  548.   { If the string is empty an unrecognized code was sent in }
  549.   if ErrorMessageString = '' then
  550.   begin
  551.     { Sent up db based on source or target error; reset cursor for neatness }
  552.     Screen.Cursor := crDefault;
  553.     MessageDlg( OperationString + ExtractFileName( ThePath ) + ' Error Code: ' +
  554.      IntToStr( TheCode ) , mtError , [mbOK],0);
  555.   end
  556.   else  { Code is recognized, use message from case statement }
  557.   begin
  558.     { Format the output for source or target error }
  559.     Screen.Cursor := crDefault;
  560.     MessageDlg( OperationString + ExtractFilePath( ThePath ) + ' ' +
  561.      ErrorMessageString , mtError , [mbOK], 0 );
  562.   end;
  563. end;
  564.  
  565. { This procedure sets the imported booleans to the file's attributes }
  566. procedure TFileWorkBench.GetFileAttributes( TheFile : String; var IsDirectory ,
  567.            IsArchive , IsVolumeID , IsHidden , IsReadOnly ,
  568.             IsSysFile : Boolean );
  569. var TheResult : Integer; { Traps for error code on VolumeID }
  570. begin
  571.   { Clear the imported flags for default }
  572.   IsDirectory := false;
  573.   IsArchive := false;
  574.   IsVolumeID := false;
  575.   IsHidden := False;
  576.   IsReadOnly := false;
  577.   IsSysFile := false;
  578.   { Make the Dos call }
  579.   TheResult := FileGetAttr( TheFile );
  580.   if TheResult < 0 then
  581.   begin
  582.     { Volume ID returns -2 (?) }
  583.     IsVolumeID := true;
  584.     { It has no other properties }
  585.     exit;
  586.   end;
  587.   { Use AND test to set all other properties }
  588.   if (( TheResult and faDirectory ) = faDirectory ) then IsDirectory := true;
  589.   if (( TheResult and faArchive ) = faArchive ) then IsArchive := true;
  590.   if (( TheResult and faVolumeID ) = faVolumeID ) then IsVolumeID := true;
  591.   if (( TheResult and faReadOnly ) = faReadOnly ) then IsReadOnly := true;
  592.   if (( TheResult and faHidden ) = faHidden ) then IsHidden := true;
  593.   if (( TheResult and faSysFile ) = faSysFile ) then IsSysFile := true;
  594. end;
  595.  
  596. { This function makes sure a pathname has a trailing \ }
  597. function TFileWorkBench.ForceTrailingBackSlash(
  598.           const TheFileName : String ) : String;
  599. var TempString : String;  { Used to hold function result }
  600. begin
  601.   { If no trailing \ add one (root will already have one.) }
  602.   if TheFileName[ Length( TheFileName ) ] <> '\' then
  603.    TempString := TheFileName + '\' else TempString := TheFileName;
  604.   { Return modified or non-modified string }
  605.   ForceTrailingBackslash := TempString;
  606. end;
  607.  
  608. { This function makes sure a non-root dir has no trailing \ }
  609. function TFileWorkBench.StripNonRootTrailingBackSlash(
  610.           const TheFileName : String ) : String;
  611. var TempString : String ; { Used to hold function result }
  612. begin
  613.   { Default is no change }
  614.   TempString := TheFileName;
  615.   { If not root then }
  616.   if Length( TheFileName ) > 3 then
  617.   begin
  618.     { If has a trailing backslash remove it }
  619.     if TheFileName[ Length( TheFileName )] = '\' then
  620.     begin
  621.       TempString := Copy( TheFileName , 1 ,
  622.        Length( TheFileName ) - 1 );
  623.     end;
  624.   end;
  625.   { Export the final result }
  626.   StripNonRootTrailingBackSlash := TempString;
  627. end;
  628.  
  629. { This gets the next selected listbox item }
  630. function TIconFileListBox.GetNextSelection( SourceDirectory : String;
  631.           var CurrentItem : Integer ): String;
  632. var TheResult : String;  { Internal storage }
  633.     finished  : boolean; { Loop flag        }
  634. begin
  635.   { If out of items to check signal and exit }
  636.   if CurrentItem > Items.Count then TheResult := '' else
  637.   begin
  638.     { Otherwise scan from current position till match or end }
  639.     finished := false;
  640.     while not finished do
  641.     begin
  642.       { Check against selected property }
  643.       if Selected[ CurrentItem - 1 ] then
  644.       begin
  645.         { If selected then return it and abort loop }
  646.         TheResult := SourceDirectory + Items[ CurrentItem - 1 ];
  647.         finished := true;
  648.         { Increment current position }
  649.         CurrentItem := CurrentItem + 1;
  650.      end
  651.       else
  652.       begin
  653.         { Increment current position }
  654.         CurrentItem := CurrentItem + 1;
  655.         { Otherwise check for end of data and abort if out of entries }
  656.         if CurrentItem > Items.Count then
  657.         begin
  658.           TheResult := '';
  659.           finished := true;
  660.         end;
  661.       end;
  662.     end;
  663.   end;
  664.   { Return stored result }
  665.   GetNextSelection := TheResult;
  666. end;
  667.  
  668. { Create method for FIP                                }
  669. constructor TFileIconPanel.Create( AOwner : TComponent );
  670. begin
  671.   { call inherited -- VITAL! }
  672.   inherited Create( AOwner );
  673.   { create icon and label components, making self owner/displayer }
  674.   FTheIcon := TIcon.Create;
  675.   FTheLabel := TLabel.Create( Self );
  676.   FThelabel.Parent := Self;
  677.   { Set own and labels mouse methods to stored methods }
  678.   OnClick := TheClick;
  679.   FTheLabel.OnClick := TheClick;
  680.   { Set alignment and autosize properties of the label }
  681.   FTheLabel.Autosize := false;
  682.   FTheLabel.Alignment := taCenter;
  683.   { Set selected to false }
  684.   Selected := false;
  685. end;
  686.  
  687. { Initialization method for FIP                                         }
  688. procedure TFileIconPanel.Initialize( PanelX              ,
  689.                                      PanelY              ,
  690.                                      PanelWidth          ,
  691.                                      PanelHeight         ,
  692.                                      PanelBevelWidth     ,
  693.                                      LabelFontSize         : Integer;
  694.                                      PanelColor          ,
  695.                                      PanelHighlightColor ,
  696.                                      PanelShadowColor    ,
  697.                                      LabelTextColor        : TColor;
  698.                                      TheFilename         ,
  699.                                      LabelFontName         : String;
  700.                                      LabelFontStyle        : TFontStyles;
  701.                                      ExtraData             : Integer );
  702.  
  703. var TheLabelHeight ,             { Holder for label pixel height }
  704.     TheLabelWidth    : Integer;  { Holder for label pixel width  }
  705.     TheOtherPChar    : PChar;    { Windows ASCIIZ string         }
  706. begin
  707.   { Set the basic properties based on imported parameters }
  708.   Left := PanelX;
  709.   Top := PanelY;
  710.   Width := PanelWidth;
  711.   Height := PanelHeight;
  712.   Color := PanelColor;
  713.   BevelWidth := PanelBevelWidth;
  714.   FHighlightColor := PanelHighlightColor;
  715.   FShadowColor := PanelShadowColor;
  716.   FTheName := TheFilename;
  717.   { If the ExtraData field is non-0 then a drive is being sent in }
  718.   if ExtraData <> 0 then
  719.   begin
  720.     { Use the data field value to determine which icon to get from RES file }
  721.     case ExtraData of
  722.       1 : begin
  723.             GetMem( TheOtherPChar , 255 );
  724.             StrPCopy( TheOtherPChar , 'FLOPPY35' );
  725.             FTheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  726.             FreeMem( TheOtherPChar , 255 );
  727.           end;
  728.       2 : begin
  729.             GetMem( TheOtherPChar , 255 );
  730.             StrPCopy( TheOtherPChar , 'FIXEDHD' );
  731.             FTheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  732.             FreeMem( TheOtherPChar , 255 );
  733.           end;
  734.       3 : begin
  735.             GetMem( TheOtherPChar , 255 );
  736.             StrPCopy( TheOtherPChar , 'NETWORKHD' );
  737.             FTheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  738.             FreeMem( TheOtherPChar , 255 );
  739.           end;
  740.       4 : begin
  741.             GetMem( TheOtherPChar , 255 );
  742.             StrPCopy( TheOtherPChar , 'CDROM' );
  743.             FTheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  744.             FreeMem( TheOtherPChar , 255 );
  745.           end;
  746.       5 : begin
  747.             GetMem( TheOtherPChar , 255 );
  748.             StrPCopy( TheOtherPChar , 'RAM' );
  749.             FTheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  750.             FreeMem( TheOtherPChar , 255 );
  751.           end;
  752.     end;
  753.     { The FileNme property is already set up for the caption; use directly }
  754.     FTheLabel.Caption := TheFilename;
  755.     { Set up the hint for later use (make sure to set ShowHint) }
  756.     Hint := 'Change to ' + TheFileName;
  757.     ShowHint := true;
  758.     { Set up all imported label properties and center it for drawing }
  759.     with FTheLabel do
  760.     begin
  761.       Font.Name := LabelFontName;
  762.       Font.Size := LabelFontSize;
  763.       Font.Style := LabelFontStyle;
  764.       Font.Color := LabelTextColor;
  765.       Canvas.Brush.Color := PanelColor;
  766.       Canvas.Font := Font;
  767.       TheLabelHeight := Canvas.Textheight( Caption ) + 4;
  768.       TheLabelWidth := Canvas.Textwidth( Caption ) + 4;
  769.       Left := (( Self.Width - TheLabelWidth ) div 2 ) + 1;
  770.       Top := ((( Round( Self.Height * 0.25 ) - 6 ) - TheLabelHeight) div 2) + 1;
  771.       Top := Top + Round( Self.Height * 0.75 );
  772.       Height := TheLabelHeight;
  773.       Width := TheLabelWidth;
  774.     end;
  775.   end
  776.   else
  777.   begin
  778.     { A file or directory has been sent in; use GetIconForFile to obtain an }
  779.     { icon either from the file, its owner, or a RES file default.          }
  780.     GetIconForFile( FTheName , FTheIcon );
  781.     { Check for the Backup caption and set it specially }
  782.     if ExtractfileName( FThename ) = '..' then
  783.     begin
  784.       FTheLabel.Caption := '..';
  785.       Hint := 'Up One Level';
  786.     end
  787.     else
  788.     begin
  789.       { Otherwise just get the filename for the label caption }
  790.       { And the full path for the hint (used later.)          }
  791.       FTheLabel.caption := ExtractFileName( UpperCase( FTheName ));
  792.       Hint := FTheName;
  793.     end;
  794.     { Activate showhint so hints are seen }
  795.     ShowHint := true;
  796.     { Set label properties with imported values and center for display }
  797.     with FTheLabel do
  798.     begin
  799.       Font.Name := LabelFontName;
  800.       Font.Size := LabelFontSize;
  801.       Font.Style := LabelFontStyle;
  802.       Font.Color := LabelTextColor;
  803.       Canvas.Brush.Color := PanelColor;
  804.       Canvas.Font := Font;
  805.       TheLabelHeight := Canvas.Textheight( Caption ) + 4;
  806.       TheLabelWidth := Canvas.Textwidth( Caption ) + 4;
  807.       Left := (( Self.Width - TheLabelWidth ) div 2 ) + 1;
  808.       Top := ((( Round( Self.Height * 0.25 ) - 6 ) - TheLabelHeight) div 2) + 1;
  809.       Top := Top + Round( Self.Height * 0.75 );
  810.       Height := TheLabelHeight;
  811.       Width := TheLabelWidth;
  812.     end;
  813.   end;
  814. end;
  815.  
  816. { Destroy method for FIP }
  817. destructor TFileIconPanel.Destroy;
  818. begin
  819.   { free component resources }
  820.   FTheIcon.Free;
  821.   FTheLabel.Free;
  822.   { call inherited -- VITAL! }
  823.   inherited Destroy;
  824. end;
  825.  
  826. { TheClick method for FIP; used for event responses }
  827. procedure TFileIconPanel.TheClick( Sender : TObject );
  828. begin
  829.   { Currently ignore drive clicks }
  830.   if Pos( 'DRIVE' , FTheName ) > 0 then exit;
  831.   { Flip status of bevels }
  832.   if BevelOuter = bvRaised then BevelOuter := bvLowered else
  833.    BevelOuter := bvRaised;
  834.   { Flip selected variable }
  835.   Selected := not Selected;
  836.   { Set redisplay }
  837.   Invalidate;
  838. end;
  839.  
  840. { Paint method for FIP; overrides normal paint }
  841. procedure TFileIconPanel.Paint;
  842. var
  843.   TheOtherRect   : TRect;   { Holds clientrect   }
  844.   TopColor     ,            { Holds bright color }
  845.   BottomColor    : TColor;  { Holds dark color   }
  846.  
  847. { These methods are from Borland Intl., copyright 1995 }
  848. procedure Frame3D(    Canvas       : TCanvas;
  849.                   var TheRect      : TRect;
  850.                       TopColor   ,
  851.                       BottomColor  : TColor;
  852.                       Width        : Integer );
  853.  
  854. procedure DoRect;
  855. var
  856.   TopRight, BottomLeft: TPoint;
  857. begin
  858.   with Canvas, TheRect do
  859.   begin
  860.     TopRight.X := Right;
  861.     TopRight.Y := Top;
  862.     BottomLeft.X := Left;
  863.     BottomLeft.Y := Bottom;
  864.     Pen.Color := TopColor;
  865.     PolyLine([BottomLeft, TopLeft, TopRight]);
  866.     Pen.Color := BottomColor;
  867.     Dec(BottomLeft.X);
  868.     PolyLine([TopRight, BottomRight, BottomLeft]);
  869.   end;
  870. end;
  871.  
  872. begin
  873.   Canvas.Pen.Width := 1;
  874.   Dec(TheRect.Bottom); Dec(TheRect.Right);
  875.   while Width > 0 do
  876.   begin
  877.     Dec(Width);
  878.     DoRect;
  879.     InflateRect(TheRect, -1, -1);
  880.   end;
  881.   Inc(TheRect.Bottom); Inc(TheRect.Right);
  882. end;
  883.  
  884. procedure AdjustColors(Bevel: TPanelBevel);
  885. begin
  886.   TopColor := FHighlightColor;
  887.   if Bevel = bvLowered then TopColor := FShadowColor;
  888.   BottomColor := FShadowColor;
  889.   if Bevel = bvLowered then BottomColor := FHighlightColor;
  890. end;
  891.  
  892. { Custom code begins here }
  893. begin
  894.   { Get the rectangle of the control with API/method call }
  895.   TheOtherRect := GetClientRect;
  896.   { draw basic rectangle with basic color }
  897.   with Canvas do
  898.   begin
  899.     Brush.Color := Color;
  900.     FillRect(TheOtherRect);
  901.   end;
  902.   { Set up for top "icon" frame  and draw it with frame3d }
  903.   TheOtherRect.Right := Width;
  904.   TheOtherRect.Bottom := Round( Height * 0.75 ) - 6 ;
  905.   if BevelOuter <> bvNone then
  906.   begin
  907.     AdjustColors(BevelOuter);
  908.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  909.   end;
  910.   Frame3D(Canvas, TheOtherRect, Color, Color, BorderWidth);
  911.   if BevelInner <> bvNone then
  912.   begin
  913.     AdjustColors(BevelInner);
  914.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  915.   end;
  916.   { Do the same for the lower "label" frame }
  917.   TheOtherRect.Top := Round( Height * 0.75 ) - 5;
  918.   TheOtherRect.Left := 0;
  919.   TheOtherRect.Bottom := Height;
  920.   TheOtherRect.Right := Width;
  921.   if BevelOuter <> bvNone then
  922.   begin
  923.     AdjustColors(BevelOuter);
  924.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  925.   end;
  926.   Frame3D(Canvas, TheOtherRect, Color, Color, BorderWidth);
  927.   if BevelInner <> bvNone then
  928.   begin
  929.     AdjustColors(BevelInner);
  930.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  931.   end;
  932.   { Then draw the icon using canvas draw method }
  933.   Canvas.Draw( (( Width - 32 ) div 2 ) + 1 ,
  934.   ((( Round( Height * 0.75 ) - 6 ) - 32 ) div 2 ) + 1 , FTheIcon );
  935. end;
  936.  
  937. { This procedure clears a scrollbox of all FileIconPanels }
  938. procedure TFileIconPanelScrollbox.ClearTheFIPs;
  939. var Counter_1 : Integer;
  940.     TheComponent : TComponent;
  941. begin
  942.   { Note that must use while loop since component count continually }
  943.   { decreases as removes are made!                                  }
  944.   while ComponentCount > 0 do
  945.   begin
  946.     { Save the component as a generic TComponent }
  947.     TheComponent := Components[ 0 ];
  948.     { Call removecomponent to pull it out of the owner list for sb }
  949.     { This avoids GPF when freeing the sb.                         }
  950.     RemoveComponent( Components[ 0 ]);
  951.     { Typecast the pointer and free it to release memory and res. }
  952.     TFileIconPanel( TheComponent ).Free;
  953.   end;
  954. end;
  955.  
  956. { This procedure scans for drives and obtains their type and creates file }
  957. { icon panels to represent them.                                          }
  958. procedure TFileIconPanelScrollBox.AddDriveIcons( var XCounter ,
  959.            YCounter : Integer );
  960. type
  961.   { This if from filectrl unit; reproduce here for completeness }
  962.   TDriveType = (dtUnknown, dtNoDrive, dtFloppy, dtFixed, dtNetwork, dtCDROM,
  963.                 dtRAM);
  964. var
  965.   DrivePC         : array[0..256] of char;
  966.   DriveNum        : Integer;         { Used to get next drive via DOS fn   }
  967.   IconType        : Integer;         { Used to hold icon type (defacto dt) }
  968.   DriveChar       : Char;            { Used to hold drive letter           }
  969.   DriveType       : TDriveType;      { Used for set-valued drive type      }
  970.   Finished        : Boolean;         { Loop flag                           }
  971.   TheFIP          : TFileIconPanel;  { Generic FileIconPanel variable      }
  972.   ButtonColor   ,                    { Main panel color                    }
  973.   ButtonHLColor ,                    { Bright panel color                  }
  974.   ButtonSColor  ,                    { Dark panel color                    }
  975.   Textcolor       : TColor;          { Label text color                    }
  976.  
  977. (*{ This code is from the FileCtrl Unit; copyright Borland Intl 1995      }
  978. { Check whether drive is a CD-ROM.  Returns True if MSCDEX is installed }
  979. {  and the drive is using a CD driver                                   }
  980.  
  981. function IsCDROM(DriveNum: Integer): Boolean; assembler;
  982. asm
  983.   MOV   AX,1500h { look for MSCDEX }
  984.   XOR   BX,BX
  985.   INT   2fh
  986.   OR    BX,BX
  987.   JZ    @Finish
  988.   MOV   AX,150Bh { check for using CD driver }
  989.   MOV   CX,DriveNum
  990.   INT   2fh
  991.   OR    AX,AX
  992.   @Finish:
  993. end;
  994.  
  995. { This code is from the FileCtrl Unit; copyright Borland Intl 1995      }
  996. { Check whether drive is a RAM drive.                                   }
  997. function IsRAMDrive(DriveNum: Integer): Boolean; assembler;
  998. var
  999.   TempResult: Boolean;
  1000. asm
  1001.   MOV   TempResult,False
  1002.   PUSH  DS
  1003.   MOV   BX,SS
  1004.   MOV   DS,BX
  1005.   SUB   SP,0200h
  1006.   MOV   BX,SP
  1007.   MOV   AX,DriveNum
  1008.   MOV   CX,1
  1009.   XOR   DX,DX
  1010.   INT   25h  { read boot sector }
  1011.   ADD   SP,2
  1012.   JC    @ItsNot
  1013.   MOV   BX,SP
  1014.   CMP   BYTE PTR SS:[BX+15h],0F8h  { reverify fixed disk }
  1015.   JNE   @ItsNot
  1016.   CMP   BYTE PTR SS:[BX+10h],1  { check for single FAT }
  1017.   JNE   @ItsNot
  1018.   MOV   TempResult,True
  1019.   @ItsNot:
  1020.   ADD   SP,0200h
  1021.   POP   DS
  1022.   MOV   AL, TempResult
  1023. end;
  1024.  
  1025. { This code is from the FileCtrl Unit; copyright Borland Intl 1995      }
  1026. { Finds the type of a drive letter.                                     }
  1027. function FindDriveType(DriveNum: Integer): TDriveType;
  1028. begin
  1029.   Result := TDriveType(GetDriveType(DriveNum));
  1030.   if (Result = dtFixed) or (Result = dtNetwork) then
  1031.   begin
  1032.     if IsCDROM(DriveNum) then Result := dtCDROM
  1033.     else if (Result = dtFixed) then
  1034.     begin
  1035.         { do not check for RAMDrive under Windows NT }
  1036.       if ((GetWinFlags and $4000) = 0) and IsRAMDrive(DriveNum) then
  1037.         Result := dtRAM;
  1038.     end;
  1039.   end;
  1040. end;*)
  1041.  
  1042. begin
  1043.   { Set the button colors to an aquamarine color scheme for drives }
  1044.   ButtonColor := clTeal;
  1045.   ButtonHLColor := clAqua;
  1046.   ButtonSColor := clNavy;
  1047.   TextColor := clblack;
  1048.   { Set initial variables before looping for all drives }
  1049.   finished := false;
  1050.   DriveNum := 0;
  1051.   while not finished do
  1052.   begin
  1053.     { Start with no drive found }
  1054.     IconType := 0;
  1055.     (*=============REMOVED DUE TO WINDOWS 95=========
  1056.     { Call the Borland method to get the drive info }
  1057.     DriveType := FindDriveType(DriveNum);
  1058.     ===============END WINDOWS 95 REMOVAL==========*)
  1059.     { Set its letter and make it uppercase }
  1060.     DriveChar := Chr(DriveNum + ord('a'));
  1061.     DriveChar := Upcase(DriveChar);
  1062.     StrPCopy( DrivePC , DriveChar + ':\' );
  1063.     {*&&&&&&&&&&&&&&&  WIN 95 CALL  &&&&&&&&&&&&&&&&&&&*}
  1064.     DriveType := TDriveType(GetDriveType( DrivePC ));
  1065.     { Assign an icon based on the drive type; if no drive exists type is nil }
  1066.     case DriveType of
  1067.       dtFloppy  : IconType := 1;
  1068.       dtFixed   : IconType := 2;
  1069.       dtNetwork : IconType := 3;
  1070.       dtCDROM   : IconType := 4;
  1071.       dtRAM     : IconType := 5;
  1072.     end;
  1073.     { Set to check next drive letter }
  1074.     DriveNum := DriveNum + 1;
  1075.     { But if no match then out of drives so set exit flag }
  1076.     if IconType = 0 then finished := true;
  1077.     { If drive was valid then set up the new FileIconPanel on the imported }
  1078.     { Scrollbox                                                            }
  1079.     if not finished then
  1080.     begin
  1081.       { Create the FileIconPanel and set its parent for memory mgmt and display}
  1082.       TheFIP := TFileIconPanel.Create( Self );
  1083.       TheFIP.Parent := Self;
  1084.       { Call its initialize method with imported position values and the   }
  1085.       { preset color scheme, a drive caption, and a minimum font. Note the }
  1086.       { setting of the ExtraData field to non-zero; this signals a drive   }
  1087.       { rather than a file being sent in.                                  }
  1088.       TheFIP.Initialize((( XCounter - 1 ) * TheIconSpacing ),
  1089.        (( YCounter - 1  ) * TheIconSpacing ) , TheIconSize , TheIconSize , 3 ,
  1090.         7 , ButtonColor, ButtonHLColor,
  1091.        ButtonSColor , TextColor , 'DRIVE ' + DriveChar + ':' , 'MS Serif' , [] ,
  1092.        IconType );
  1093.       { Increment the column counter; if it exceeds max move to new row      }
  1094.       { Note that these are 'var' parameters and will export final position. }
  1095.       XCounter := XCounter + 1;
  1096.       if XCounter > MaxIconsInARow then
  1097.       begin
  1098.         XCounter := 1;
  1099.         YCounter := YCounter + 1;
  1100.       end;
  1101.     end;
  1102.   end;
  1103. end;
  1104.  
  1105. { This procedure assigns colors to FIP's based on file attributes }
  1106. procedure TFileIconPanelScrollBox.GetColorsForFileIcon( TheFile : String;
  1107.            var BC , HC , SC , TC : TColor );
  1108. var AmADir      ,             { Booleans hold file attribs }
  1109.     AmAnArchive ,
  1110.     AmAVolumeId ,
  1111.     AmHidden    ,
  1112.     AmReadOnly  ,
  1113.     AmSystem      : Boolean;
  1114. begin
  1115.   { Make the call to internal fileworkbench to set attributes }
  1116.   TheFWB.GetFileAttributes( TheFile , AmADir , AmAnArchive , AmAVolumeId ,
  1117.    AmHidden , AmReadOnly , AmSystem );
  1118.   { Volume ID has no subtypes }
  1119.   if AmAVolumeID then
  1120.   begin
  1121.     BC := clOlive;
  1122.     HC := clYellow;
  1123.     SC := clBlack;
  1124.     TC := clWhite;
  1125.     exit;
  1126.   end;
  1127.   { Check all directory combinations }
  1128.   if AmADir then
  1129.   begin
  1130.     BC := clNavy;
  1131.     HC := clBlue;
  1132.     SC := clBlack;
  1133.     TC := clWhite;
  1134.     if AmHidden then
  1135.     begin
  1136.       if AmReadOnly then
  1137.       begin
  1138.         if AmSystem then
  1139.         begin { One HECK of a file! }
  1140.           BC := clBlack;
  1141.           HC := clSilver;
  1142.           SC := clGray;
  1143.           TC := clWhite;
  1144.         end
  1145.         else
  1146.         begin { Dir,RO,Hid }
  1147.           BC := clMaroon;
  1148.           HC := clFuchsia;
  1149.           SC := clGreen;
  1150.           TC := clWhite;
  1151.         end;
  1152.       end
  1153.       else
  1154.       begin { Dir,Hid }
  1155.         BC := clPurple;
  1156.         HC := clFuchsia;
  1157.         SC := clBlack;
  1158.         TC := clWhite;
  1159.       end;
  1160.     end
  1161.     else
  1162.     begin
  1163.       if AmReadOnly then
  1164.       begin
  1165.         if AmSystem then
  1166.         begin { Dir,RO,Sys }
  1167.           BC := clMaroon;
  1168.           HC := clLime;
  1169.           SC := clGreen;
  1170.           TC := clWhite;
  1171.         end
  1172.         else
  1173.         begin { Dir,RO }
  1174.           BC := clGreen;
  1175.           HC := clLime;
  1176.           SC := clBlack;
  1177.           TC := clWhite;
  1178.         end;
  1179.       end
  1180.       else
  1181.       begin
  1182.         if AmSystem then
  1183.         begin { Dir,Sys }
  1184.           BC := clMaroon;
  1185.           HC := clRed;
  1186.           SC := clBlack;
  1187.           TC := clWhite;
  1188.         end;
  1189.       end;
  1190.     end;
  1191.   end
  1192.   else { Archive Only; check all combinations }
  1193.   begin
  1194.     BC := clSilver;
  1195.     HC := clWhite;
  1196.     SC := clGray;
  1197.     TC := clBlack;
  1198.     if AmHidden then
  1199.     begin
  1200.       if AmReadOnly then
  1201.       begin
  1202.         if AmSystem then
  1203.         begin { Hid,RO,Sys }
  1204.           BC := clRed;
  1205.           HC := clLime;
  1206.           SC := clPurple;
  1207.           TC := clBlack;
  1208.         end
  1209.         else
  1210.         begin { RO,Hid }
  1211.           BC := clLime;
  1212.           HC := clFuchsia;
  1213.           SC := clMaroon;
  1214.           TC := clBlack;
  1215.         end;
  1216.       end
  1217.       else
  1218.       begin { Hid }
  1219.         BC := clFuchsia;
  1220.         HC := clWhite;
  1221.         SC := clPurple;
  1222.         TC := clBlack;
  1223.       end;
  1224.     end
  1225.     else
  1226.     begin
  1227.       if AmReadOnly then
  1228.       begin
  1229.         if AmSystem then
  1230.         begin { RO,Sys }
  1231.           BC := clRed;
  1232.           HC := clLime;
  1233.           SC := clMaroon;
  1234.           TC := clBlack;
  1235.         end
  1236.         else
  1237.         begin { RO }
  1238.           BC := clLime;
  1239.           HC := clWhite;
  1240.           SC := clGreen;
  1241.           TC := clBlack;
  1242.         end;
  1243.       end
  1244.       else
  1245.       begin
  1246.         if AmSystem then
  1247.         begin { System }
  1248.           BC := clRed;
  1249.           HC := clWhite;
  1250.           SC := clMaroon;
  1251.           TC := clBlack;
  1252.         end;
  1253.       end;
  1254.     end;
  1255.   end;
  1256. end;
  1257.  
  1258. { This procedure gets all icons for an given directory, including drives and }
  1259. { standard subdirectories. It does not get special combinations or h/ro/sys  }
  1260. procedure TFileIconPanelScrollbox.GetIconsForEntireDirectory(
  1261.             TargetPath  : String );
  1262. var Finished        : Boolean;         { Loop flag              }
  1263.     TheSR           : TSearchRec;      { Searchrecord for FF/FN }
  1264.     TheResult       : Integer;         { return variable        }
  1265.     TempPath        : String;          { path for FF/FN         }
  1266.     TheFIP          : TFileIconPanel;  { generic FIP holder     }
  1267.     RowCounter    ,                    { position in row of FIP }
  1268.     ColumnCounter   : Integer;         { position in col of FIP }
  1269.     ButtonColor   ,                    { main panel color       }
  1270.     ButtonHLColor ,                    { bright panel color     }
  1271.     ButtonSColor  ,                    { dark panel color       }
  1272.     Textcolor       : TColor;          { label text color       }
  1273.     IsADir ,                           { Variable for file attr }
  1274.     IsAnArchive ,
  1275.     IsAVolumeID,
  1276.     IsAReadOnlyFile,
  1277.     IsAHiddenFile ,
  1278.     IsASystemFile     : Boolean;
  1279.     MaxTextLength     : Integer;       { Used to safely set size}
  1280. begin
  1281.   { hide during refresh }
  1282.   Visible := false;
  1283.   { Delete the current set, if any }
  1284.   ClearTheFIPs;
  1285.   { Get the icon sizes }
  1286.   TheFIP := TFileIconPanel.Create( Self );
  1287.   TheFIP.Parent := Self;
  1288.   TheFIP.FTheLabel.Canvas.Font.Name := 'MS Serif';
  1289.   TheFIP.FTheLabel.Canvas.Font.Size := 7;
  1290.   MaxTextLength := TheFIP.FTheLabel.Canvas.TextWidth( 'COMMAND.COM' );
  1291.   TheFIP.Free;
  1292.   TheIconSize := MaxTextLength + 13;
  1293.   TheIconSpacing := TheIconSize + 5;
  1294.   { Set up maximum icons per row based on screen size }
  1295.   MaxIconsInARow := ( Screen.Width div TheIconSpacing );
  1296.   { Set up the position counters }
  1297.   RowCounter := 1;
  1298.   ColumnCounter := 1;
  1299.   { Get the drives for the current machine }
  1300.   AddDriveIcons( ColumnCounter , RowCounter  );
  1301.   { Set up the initial variables }
  1302.   Finished := false;
  1303.   TempPath := TargetPath + '*.*';
  1304.   { Make the call to FindFirst set to get any file; will return '.' }
  1305.   { so discard it.                                                  }
  1306.   TheResult := FindFirst( TempPath , faAnyFile , TheSR );
  1307.   { loop through all files in the directory and look for directories }
  1308.   while not Finished do
  1309.   begin
  1310.     { Make call to FindNext, using only SearchRecord from FindFirst }
  1311.     TheResult := FindNext( TheSR );
  1312.     { A -1 result means no more files so exit }
  1313.     if TheResult <> 0 then finished := true else
  1314.     begin
  1315.       { Otherwise check for a directory attribute }
  1316.       if (( FileGetAttr( TargetPath + TheSR.Name ) and faDirectory ) =
  1317.        faDirectory ) then
  1318.       begin
  1319.         GetColorsForFileIcon( TargetPath + TheSR.Name , ButtonColor ,
  1320.          ButtonHLColor , ButtonSColor , TextColor );
  1321.         { If found create a new FileIconPanel on the imported scrollbox }
  1322.         { Note sending 0 ExtraData parameter to indicate file not drive }
  1323.         TheFIP := TFileIconPanel.Create( Self );
  1324.         TheFIP.Parent := Self;
  1325.         TheFIP.Initialize((( ColumnCounter - 1 ) * TheIconSpacing ),
  1326.          (( RowCounter - 1  ) * TheIconSpacing ) , TheIconSize, TheIconSize ,
  1327.           3 , 7 , ButtonColor, ButtonHLColor , ButtonSColor , TextColor ,
  1328.            TargetPath + TheSr.Name , 'MS Serif' , [] , 0 );
  1329.         { Increment column counter and move to new row if past limit }
  1330.         ColumnCounter := ColumnCounter + 1;
  1331.         if ColumnCounter > MaxIconsInARow then
  1332.         begin
  1333.           ColumnCounter := 1;
  1334.           RowCounter := RowCounter + 1;
  1335.         end;
  1336.       end;
  1337.     end;
  1338.   end;
  1339.   { Set up new initialization variables }
  1340.   Finished := false;
  1341.   TempPath := TargetPath + '*.*';
  1342.   { Make needed call to FindFirst and discard '.' }
  1343.   TheResult := FindFirst( TempPath , faAnyFile , TheSR );
  1344.   while not Finished do
  1345.   begin
  1346.     { Loop through file again, this time getting only archive files }
  1347.     TheResult := FindNext( TheSR );
  1348.     { Result of -1 indicates no more files }
  1349.     if TheResult <> 0 then Finished := true else
  1350.     begin
  1351.       { If faArchive file then add new FileIconPanel }
  1352.       TheFWB.GetFileAttributes(( Targetpath + TheSR.Name ) , IsADir ,
  1353.        IsAnArchive , IsAVolumeId , IsAHiddenFile , IsAReadOnlyFile ,
  1354.         IsASystemFile );
  1355.       if (( IsAnArchive ) and ( not IsADir )) then
  1356.       begin
  1357.         GetColorsForFileIcon( TargetPath + TheSR.Name , ButtonColor ,
  1358.          ButtonHLColor , ButtonSColor , TextColor );
  1359.         { Initialize new FileIconPanel and call initialize, sending 0 ED }
  1360.         TheFIP := TFileIconPanel.Create( Self );
  1361.         TheFIP.Parent := Self;
  1362.         TheFIP.Initialize((( ColumnCounter - 1 ) * TheIconSpacing ),
  1363.          (( RowCounter - 1  ) * TheIconSpacing ) , TheIconSize , TheIconSize ,
  1364.           3 , 7 , ButtonColor, ButtonHLColor , ButtonSColor , TextColor ,
  1365.            TargetPath + TheSr.Name , 'MS Serif' , [] , 0 );
  1366.         { Increment column counter and if needed row counter }
  1367.         ColumnCounter := ColumnCounter + 1;
  1368.         if ColumnCounter > MaxIconsInARow then
  1369.         begin
  1370.           ColumnCounter := 1;
  1371.           RowCounter := RowCounter + 1;
  1372.         end;
  1373.       end;
  1374.     end;
  1375.   end;
  1376.   { Reset to visible }
  1377.   Visible := true;
  1378. end;
  1379.  
  1380. { Update method for FIPscrollbox }
  1381. procedure TFileIconPanelScrollBox.Update;
  1382. begin
  1383.   IconsNeedRefreshing := true;
  1384.   { Force a repaint }
  1385.   InvalidateRect( TheStoredHandle , nil , true );
  1386. end;
  1387.  
  1388. { Create method for FIPScrollbox }
  1389. constructor TFileIconPanelScrollBox.Create( AOwner : TComponent );
  1390. begin
  1391.   inherited Create( AOwner );
  1392.   TheFWB := TFileWorkBench.Create( Self );
  1393. end;
  1394.  
  1395. { This function returns the next selected file's name }
  1396. function TFileIconPanelScrollBox.GetNextSelection( SourceDirectory : String;
  1397.                            var CurrentItem : Integer ) : String;
  1398. var TheResult    : String;      { Holds result of function }
  1399.     TheComponent : TComponent;  { Used for typecast        }
  1400.     finished     : boolean;     { Loop control variable    }
  1401.     TheComponentCount : Integer;
  1402. begin
  1403.   TheComponentCount := ComponentCount;
  1404.   { If past end of components exit with no result }
  1405.   if CurrentItem > TheComponentCount then TheResult := '' else
  1406.   begin
  1407.     { Set loop counter and run till find match or run out }
  1408.     finished := false;
  1409.     while not finished do
  1410.     begin
  1411.       { Pull component out of the list and check it }
  1412.       TheComponent := Components[ CurrentItem - 1 ];
  1413.       { Increment counter for later }
  1414.       CurrentItem := CurrentItem + 1;
  1415.       { Do the typecast with AS }
  1416.       with TheComponent as TFileIconPanel do
  1417.       begin
  1418.         { If its selected make sure OK }
  1419.         if Selected then
  1420.         begin
  1421.           { Don't accept backup for this level of operation }
  1422.           if FTheLabel.Caption <> '..' then
  1423.           begin
  1424.             { Otherwise return the name and abort the loop }
  1425.             TheResult := FTheName;
  1426.             finished := true;
  1427.           end;
  1428.         end
  1429.         else
  1430.         begin
  1431.           { Check to see if out of components }
  1432.           if CurrentItem > TheComponentCount then
  1433.           begin
  1434.             { If so signal error and abort }
  1435.             TheResult := '';
  1436.             finished := true;
  1437.           end;
  1438.         end;
  1439.       end;
  1440.     end;
  1441.   end;
  1442.   GetNextSelection := TheResult;
  1443. end;
  1444.  
  1445. end.
  1446.